// ES数据管理  
//     在用户注册成功时,将用户的元信息,像ES也储存一份,以便于对用户的搜索
//     搜索关键字:是一个字符串,可能是一个用户ID,也可能是一个手机号,也可能是一个昵称的一部分
//               且搜索的时候,不能搜索到自己和自己的好友,过滤条件其实就是一组用户ID
//     用户元信息:用户ID,用户昵称,手机号,签名,头像ID
//     ES的管理操作
//         1.创建用户索引
//         2.新增数据/更新数据
//         3.搜索用户(输入一个关键字,以及一组过滤用户ID)
#pragma once
#include"icsearch.hpp"
#include"user.hxx"
#include"message.hxx"

namespace wzl
{
    class ESClientFactory
    {
    public:
        static std::shared_ptr<elasticlient::Client> create(const std::vector<std::string> host_list)
        {
            return std::make_shared<elasticlient::Client>(host_list);
        }
    };

    class ESUser
    {
    public:
        using ptr = std::shared_ptr<ESUser>;
        ESUser(const std::shared_ptr<elasticlient::Client>& es_client)
            :_es_client(es_client)
        {}
        bool createIndex()
        {
            ESIndex idx(_es_client,"user");
            idx.append("user_id","keyword","standard",true);
            idx.append("nickname");
            idx.append("phone","keyword","standard",true);
            idx.append("description","text","standard",false);
            idx.append("avatar_id","keyword","standard",false);
            bool ret = idx.create();
            if(ret == false)
            {
                LOG_ERROR("用户信息索引创建失败");
                return false;
            }
            else{
                LOG_INFO("用户信息索引创建成功");
                return true;
            }
        }
        
        bool appendData(const std::string& uid,const std::string& phone,const std::string& nickname,\
            const std::string& description,const std::string& avatar_id)
        {
            ESInsert idx(_es_client,"user");
            idx.append("user_id",uid);
            idx.append("phone",phone);
            idx.append("nickname",nickname);
            idx.append("description",description);
            idx.append("avatar_id",avatar_id);
            bool ret = idx.insert(uid);
            if(ret == false)
            {
                LOG_ERROR("用户数据插入/更新失败");
                return false;
            }
            else{
                LOG_ERROR("用户数据插入/更新成功");
                return true;
            }
        }

        std::vector<User> search(const std::string& key,const std::vector<std::string>& uid_list)
        {
            std::vector<User> res;
            ESsearch sch(_es_client,"user");
            sch.append_should_match("phone.keyword",key);
            sch.append_should_match("user_id.keyword",key);
            sch.append_should_match("nickname",key);
            sch.append_must_not_terms("user_id.keyword",uid_list);
            Json::Value json_user = sch.search();
            if(json_user.isArray() == false)
            {
                LOG_ERROR("结果为空,或者数据不是数组类型");
                return res;
            }
            else{
                LOG_INFO("用户数据数据检索成功");
            }
            int sz = json_user.size();
            LOG_DEBUG("检索结果条目数量: {}",sz);
            for(int i = 0;i<sz;i++)
            {
                User user;
                user.user_id(json_user[i]["_source"]["user_id"].asString());
                user.nickname(json_user[i]["_source"]["nickname"].asString());
                user.description(json_user[i]["_source"]["description"].asString());
                user.phone(json_user[i]["_source"]["phone"].asString());
                user.avatar_id(json_user[i]["_source"]["avatar_id"].asString());
                res.push_back(user);
            }
            return res;
        }
    private:
        // const std::string _uid_key = "user_id";
        // const std::string _desc_key = "user_id";
        // const std::string _phone_key = "user_id";
        // const std::string _name_key = "user_id";
        // const std::string _avatar_key = "user_id";
        std::shared_ptr<elasticlient::Client> _es_client;
    };



    class ESMessage
    {
    public:
        using ptr = std::shared_ptr<ESMessage>;
        ESMessage(const std::shared_ptr<elasticlient::Client>& es_client)
            :_es_client(es_client)
        {}
        ~ESMessage()
        {}
        bool createIndex()
        {
            ESIndex idx(_es_client,"message");
            idx.append("user_id","keyword","standard",false);
            idx.append("message_id","keyword","standard",false);
            idx.append("create_time","long","standard",false);
            idx.append("chat_session_id","keyword","standard",true);
            idx.append("content");
            bool ret = idx.create();
            if(ret == false)
            {
                LOG_ERROR("消息信息索引创建失败");
                return false;
            }
            else{
                LOG_INFO("消息信息索引创建成功");
                return true;
            }
        }

        bool appendData(const std::string& user_id,const std::string& message_id,const long create_time,\
            const std::string& chat_session_id,const std::string& content)
        {
            ESInsert idx(_es_client,"message");
            idx.append("message_id",message_id);
            idx.append("create_time",create_time);
            idx.append("user_id",user_id);
            idx.append("chat_session_id",chat_session_id);
            idx.append("content",content);
            bool ret = idx.insert(message_id);
            if(ret == false)
            {
                LOG_ERROR("消息数据插入/更新失败");
                return false;
            }
            else{
                LOG_ERROR("消息数据插入/更新成功");
                return true;
            }

        }

        std::vector<Message> search(const std::string& key,const std::string& ssid)
        {
            std::vector<Message> res;

            ESsearch sch(_es_client,"message");
            sch.append_must_term("chat_session_id.keyword",ssid);
            sch.append_must_match("content",key);
            Json::Value json_user = sch.search();
            if(json_user.isArray() == false)
            {
                LOG_ERROR("结果为空,或者数据不是数组类型");
                return res;
            }
            else{
                LOG_INFO("用户数据数据检索成功");
            }
            int sz = json_user.size();
            LOG_DEBUG("检索结果条目数量: {}",sz);
            for(int i = 0;i<sz;i++)
            {
                Message message;
                message.user_id(json_user[i]["_source"]["user_id"].asString());
                message.message_id(json_user[i]["_source"]["message_id"].asString());
                boost::posix_time::ptime ctime(boost::posix_time::from_time_t(json_user[i]["_source"]["create_time"].asInt64()));
                message.create_time(ctime);
                message.session_id(json_user[i]["_source"]["chat_session_id"].asString());
                message.content(json_user[i]["_source"]["content"].asString());
                res.push_back(message);
            }
            return res;
            }

        bool remove(const std::string& mid)
        {
            bool ret = ESRemove(_es_client,"message").remove(mid);
            if(ret == false)
            {
                LOG_ERROR("消息数据删除失败");
                return false;
            }
            else{
                LOG_ERROR("消息数据删除成功");
                return true;
            }
        }
    private:
        std::shared_ptr<elasticlient::Client> _es_client;
    };
}